﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Encoder = System.Drawing.Imaging.Encoder;

namespace SuperKit {
    public class ImageResizer {
        public string FilePath { get; }
        private bool Zoomin { get; set; } // 是否允许放大
        private bool Zoomout { get; set; } // 是否允许缩小
        public bool KeepRate { get; set; } // 是否保持比例

        public int TargetWidth { get; }
        public int TargetHeight { get; }
        public bool Changed { get; private set; }
        public Image bitmap { get; private set; }

        public ImageResizer(string path, bool zoomin, bool zoomout, bool keepRate) {
            this.FilePath = path;
            this.Zoomin = zoomin;
            this.Zoomout = zoomout;
            this.KeepRate = keepRate;
            this.Changed = false;
        }

        /// <summary>
        /// 转化一个指定的图像。如果受到转化条件的限制，无法转化，那么返回原图片的Bitmap。
        /// </summary>
        /// <param name="width">目标的宽度</param>
        /// <param name="height">目标的高度</param>
        /// <returns></returns>
        public void Resize(int width, int height) {
            Changed = false;

            bitmap = Image.FromFile(FilePath);

            // 常规检查，如果目标相同，则不需要转化
            if (bitmap.Size.Width == width && bitmap.Size.Height == height) {
                return;
            }

            // 如果保持比例为false，那么直接配置为大小
            if (KeepRate == false) {
                ChangeTo(width, height);
            } else {
                // 如果是放大，需要检查是否允许放大
                // 放大指的是，原图像的两边都小于目标大小。如果有其中一边大于目标，都属于缩小
                if (bitmap.Width <= width && bitmap.Height <= height) { // 放大
                    if (Zoomin == false) {
                        return;
                    } else {
                        OnZoom(width, height);
                    }
                } else { // 缩小
                    if (Zoomout == false) {
                        return ;
                    } else {
                        OnZoom(width, height);
                    }
                }
            }

        }

        // 放大或者缩小一个图片
        private void OnZoom(int width, int height) {
            float rate = (float)bitmap.Width / bitmap.Height;

            // 取变化比例最小的一边
            float widthRate = (float)width / bitmap.Width;
            float heightRate = (float)height / bitmap.Height;

            int newWidth;
            int newHeight;
            if (widthRate > heightRate) {
                newHeight = height;
                newWidth = (int)(width * rate);
            } else {
                newWidth = width;
                newHeight = (int)(height / rate);
            }

            ChangeTo(newWidth, newHeight);
        }

        private void ChangeTo(int width, int height) {
            // 重新计算之后，不需要改变，则返回
            if (bitmap.Width == width && bitmap.Height == height) {
                return;
            } else {
                Changed = true;
            }

            Bitmap bmp = new Bitmap(width, height);
            Graphics g = Graphics.FromImage(bmp);
            g.DrawImage(bitmap, 0f, 0f, width, height);
            bitmap.Dispose();
            bitmap = bmp;
        }

        public void Dispose() {
            if (bitmap != null) {
                bitmap.Dispose();
                bitmap = null;
            }
        }

        public void Save(string path, long jpegQuality = 90L) {
            // 根据扩展名选择保存的类型
            var ext = Path.GetExtension(path).ToLower();
            if (ext.IndexOf("jpg") != -1 || ext.IndexOf("jpeg") != -1) { 
                ImageCodecInfo jpgEncoder = GetEncoder(ImageFormat.Jpeg);
                Encoder myEncoder = Encoder.Quality;
                EncoderParameters myEncoderParameters = new EncoderParameters(1);
                EncoderParameter myEncoderParameter = new EncoderParameter(myEncoder, jpegQuality);
                myEncoderParameters.Param[0] = myEncoderParameter;
                bitmap.Save(path, jpgEncoder, myEncoderParameters);
            } else if (ext.IndexOf("bmp") != -1) {
                bitmap.Save(path, ImageFormat.Bmp);
            } else { // 默认都是保存为png格式
                bitmap.Save(path, ImageFormat.Png);
            }
        }

        private ImageCodecInfo GetEncoder(ImageFormat format) {
            ImageCodecInfo[] codecs = ImageCodecInfo.GetImageDecoders();
            foreach (ImageCodecInfo codec in codecs) {
                if (codec.FormatID == format.Guid) {
                    return codec;
                }
            }
            return null;
        }  
    }
}
